namespace SubhadraSolutions.Sharp.Logging.Common
{
    using System.Collections.Generic;

    using SubhadraSolutions.Sharp.Utils.Data.Common;
    using SubhadraSolutions.Sharp.Utils.Diagnostics.Performance.Dtos;

    public sealed class CounterCategoryInfoDataReader : AbstractDataReader
    {
        #region Fields

        private readonly string _counterCategoryName;

        private CounterCategoryInfo _currentCategoryInfo;
        private int _currentInstanceIndex = -1;
        private CounterInstanceInfo _currentInstanceInfo;
        private IEnumerator<LogStoreItem> _enumerator;
        private long _serialNumber;

        #endregion Fields

        #region Constructors

        public CounterCategoryInfoDataReader(string counterCategoryName)
        {
            _counterCategoryName = counterCategoryName;
        }

        #endregion Constructors

        #region Indexers

        public override object this[int i]
        {
            get
            {
                switch (i)
                {
                    case 0:
                        return _serialNumber;

                    case 1:
                        return _enumerator.Current.TimeStamp;

                    case 2:
                        return _currentInstanceInfo.InstanceName;
                }
                if (i < _currentCategoryInfo.ReferenceTypeCounterNames.Count + 3)
                {
                    return _currentInstanceInfo.ReferenceTypeCounterValues[i - 3];
                }
                return
                    _currentInstanceInfo.CounterValues[
                        i - 3 - _currentCategoryInfo.ReferenceTypeCounterNames.Count];
            }
        }

        #endregion Indexers

        #region Methods

        protected override bool readProtected()
        {
            if (_currentCategoryInfo == null ||
                _currentInstanceIndex >= _currentCategoryInfo.Instances.Count - 1)
            {
                if (!_enumerator.MoveNext())
                {
                    _currentCategoryInfo = null;
                    _enumerator.Dispose();
                    _enumerator = null;
                    return false;
                }
                if (_currentCategoryInfo == null)
                {
                    return false;
                }
                if (_currentCategoryInfo.Instances.Count == 0)
                {
                    return false;
                }
                _currentInstanceIndex = -1;
            }
            _currentInstanceIndex++;
            _currentInstanceInfo = _currentCategoryInfo.Instances[_currentInstanceIndex];

            _serialNumber++;
            return true;
        }

        public void SetContext(IEnumerable<LogStoreItem> items)
        {
            _enumerator = items.GetEnumerator();
            _currentInstanceInfo = null;
            _currentInstanceIndex = -1;
            if (_enumerator.MoveNext())
            {
                var updateInfo = _enumerator.Current.LogEntry as CounterUpdateInfo;
                if (updateInfo != null)
                {
                    _currentCategoryInfo = updateInfo.GetCategoryInfo(_counterCategoryName, false);
                    if (_currentCategoryInfo != null && ColumnNames.Count == 0)
                    {
                        ColumnNames.Add("SNo");
                        ColumnNames.Add("TimeStamp");
                        ColumnNames.Add("InstanceName");
                        ColumnNames.AddRange(_currentCategoryInfo.ReferenceTypeCounterNames);
                        ColumnNames.AddRange(_currentCategoryInfo.CounterNames);
                    }
                }
            }
        }

        #endregion Methods
    }
}